#include "data_model.h"
#include "TreeItem.h"
#include <QTreeView>
#include <QModelIndex>
#include "server.h"

const QStringList ApplicationTableModel::statusStrings(QStringList() << "running" << "not running");

DataModel::DataModel(QMap<int,QList<ClientLogic*>*> *data, QObject *parent)
: QAbstractItemModel(parent), group_list(data)
{
	 setupModelData();
};

DataModel::~DataModel()
{
	delete rootItem;
}

void DataModel::setupModelData()
 {
     QList<QVariant> rootData;
     rootData << "Utente" << "Indirizzo IP";
     rootItem = new TreeItem(rootData);

	 QMapIterator<int, QList<ClientLogic *>*> i(*group_list);
     
	 while (i.hasNext()) {
			i.next();
			if(i.value()->size() > 0)
			{
				QList<QVariant> gData;
				QVariant k = i.key();
				gData << "Gruppo " + k.toString() << "";
				TreeItem *lastGroup = new TreeItem(gData,rootItem);
				
				QList<ClientLogic*> *clist = i.value();
				
				for(int j=0; j <i.value()->size(); j++)
				{
					QList<QVariant> cdata;
					cdata << clist->at(j)->getId()<< clist->at(j)->getClientAddress().toString();
					lastGroup->appendChild(new TreeItem(cdata,lastGroup));
				}
				rootItem->appendChild(lastGroup);
			}
	 }  
}

Qt::ItemFlags DataModel::flags(const QModelIndex &index) const
 {
     if (!index.isValid())
         return 0;

     return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
 }

int DataModel::rowCount(const QModelIndex &parent) const
{
	TreeItem *parentItem;

    if (!parent.isValid())
         parentItem = rootItem;
    else
         parentItem = static_cast<TreeItem*>(parent.internalPointer());

    return parentItem->childCount();
	
};
int DataModel::columnCount(const QModelIndex &parent) const
{
     if (parent.isValid())
         return static_cast<TreeItem*>(parent.internalPointer())->columnCount();
     else
         return rootItem->columnCount();
}
QVariant DataModel::data(const QModelIndex &index, int role) const
{
	if (!index.isValid())
         return QVariant();

	if (role == Qt::TextAlignmentRole) {
        return int(Qt::AlignHCenter | Qt::AlignVCenter);
	}
	
	TreeItem *item = static_cast<TreeItem*>(index.internalPointer());

	if(role == Qt::DecorationRole && item->childCount()==0 && index.column()==0)
	{
	    return QIcon(":/icons/computer.png");
	}
    if (role != Qt::DisplayRole)
        return QVariant();
    

    return item->data(index.column());
	
};
 

QModelIndex DataModel::index(int row, int column, const QModelIndex &parent)
             const
 {
     TreeItem *parentItem;

     if (!parent.isValid())
         parentItem = rootItem;
     else
         parentItem = static_cast<TreeItem*>(parent.internalPointer());

     TreeItem *childItem = parentItem->child(row);
     if (childItem)
         return createIndex(row, column, childItem);
     else
         return QModelIndex();
 }

QModelIndex DataModel::parent(const QModelIndex &index) const
 {
     if (!index.isValid())
         return QModelIndex();

     TreeItem *childItem = static_cast<TreeItem*>(index.internalPointer());
     TreeItem *parentItem = childItem->parent();

     if (parentItem == rootItem)
         return QModelIndex();

     return createIndex(parentItem->row(), 0, parentItem);
 }

QVariant DataModel::headerData(int section, Qt::Orientation orientation,
                     int role) const
{
	if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
         return rootItem->data(section);

     return QVariant();
};

bool DataModel::insertRows(int position, int rows, const QModelIndex &index)
{
	return false;
};


bool DataModel::removeRows(int position, int rows, const QModelIndex &index)
{
	return false;
}
;

void DataModel::emitChanged(int start, int end)
{
	//emit dataChanged(index(start),index(end));
};

void DataModel::emitReset()
{
	emit reset();
	setupModelData();
}



/////////////////////////////////////////////////////
//////////APPLICATION TABLE MODEL////////////////////
/////////////////////////////////////////////////////


ApplicationTableModel::ApplicationTableModel(QMap<int, ClientLogic*> *data,
	QMap<int,QList<ClientLogic*>*> *datag, QTreeView *clientsTree, Server *serverRef, QObject *parent)
	:QAbstractTableModel(parent), client_list(data), group_list(datag), _serverRef(serverRef)
{
		this->selectionModel = clientsTree->selectionModel();
		
		
};

Qt::ItemFlags ApplicationTableModel::flags(const QModelIndex &index) const
 {
     if (!index.isValid())
         return 0;

	 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
 }

void ApplicationTableModel::setRemoteAppList(QList<RemoteApplication*> &rApps) const
{
	QModelIndexList modelIndexList = this->selectionModel->selectedIndexes();
	if(modelIndexList.size() == 0 || _serverRef->isLightMode())
		return;
	
	QList<ClientLogic*> *clist;
	QMap<QString, RemoteApplication*> rAppsMap;
	QMap<QString, RemoteApplication*> rAppsMapTmp;
	QVariant variant;
	int x;
	ClientLogic* cl;

	variant = modelIndexList.at(0).model()->data(modelIndexList.at(0),Qt::DisplayRole);

	if(modelIndexList.at(0).parent().isValid())
	{
		x = variant.toInt();
		cl = client_list->value(x);
		if(!cl)
			return;
	    rAppsMap = cl->getRemoteApplications();
	}
	else
	{
		x = variant.toString().split(" ").at(1).toInt();
		clist = group_list->value(x);
		if(!clist || (clist->size() == 0) )
			return;
		
		rAppsMap = clist->at(0)->getRemoteApplications();
		if(rAppsMap.size()>0)
		{	
			for(int i=1; i<clist->size(); i++)
			{
				rAppsMapTmp = clist->at(i)->getRemoteApplications();
				QMap<QString, RemoteApplication*>::iterator it;
		
				for(it = rAppsMap.begin(); it != rAppsMap.end(); )
				{
					if(!rAppsMapTmp.contains(it.key()))
					{ 
						it = rAppsMap.erase(it);
					
					}
					else 
						it++;
				}
			}
		}
	}
	

	for(int i=2; i<modelIndexList.size(); i+=2)
	{
		variant = modelIndexList.at(i).model()->data(modelIndexList.at(i),Qt::DisplayRole );
		
		if(modelIndexList.at(i).parent().isValid())
		{
			x = variant.toInt();
			cl = client_list->value(x);
			if(!cl)
				return;
		    rAppsMapTmp = cl->getRemoteApplications();
			QMap<QString, RemoteApplication*>::iterator it;
			for(it = rAppsMap.begin(); it != rAppsMap.end(); it++)
			{
				if(!rAppsMapTmp.contains(it.key()))
				{ 
					it = rAppsMap.erase(it);
				}
			}
		}
		else
		{
			x = variant.toString().split(" ").at(1).toInt();
			clist = group_list->value(x);
			if(!clist)
				return;
			if(rAppsMap.size()>0)
			{	
				for(int k=0; k<clist->size(); k++)
				{
					rAppsMapTmp = clist->at(k)->getRemoteApplications();
					QMap<QString, RemoteApplication*>::iterator it;
		
					for(it = rAppsMap.begin(); it != rAppsMap.end(); it++)
					{
						if(!rAppsMapTmp.contains(it.key()))
						{ 
							it = rAppsMap.erase(it);
					
						}
					}
				}
			}
		}

	}
	rApps = rAppsMap.values();
	return;
}

int ApplicationTableModel::rowCount(const QModelIndex &parent) const
{
	// devo capire quali client sono stati selezionati
	QModelIndexList modelIndexList = this->selectionModel->selectedIndexes();
    QModelIndex index;
	
	if(modelIndexList.size() == 0)
		return 0;
	
	QList<RemoteApplication*> rApps;
	setRemoteAppList(rApps);

	int installed = rApps.size();
	if(installed == 0)
		return 0;
	else
		return installed;

};

int ApplicationTableModel::columnCount (  const QModelIndex & parent ) const
{
	QModelIndexList modelIndexList = this->selectionModel->selectedIndexes();
    QModelIndex index;
	if(modelIndexList.size() == 0)
		return 0;
	
	return 2;
	/*QList<RemoteApplication*> rApps;
	setRemoteAppList(rApps);

	int installed = rApps.size();
	if(installed == 0)
		return 1;
	else
		return 2;*/
	
};

QVariant ApplicationTableModel::data ( const QModelIndex & index, int role ) const
{
	if (!index.isValid())
         return QVariant();

	if (role == Qt::TextAlignmentRole) {
        return int(Qt::AlignHCenter | Qt::AlignVCenter);
	}

	QModelIndexList modelIndexList = this->selectionModel->selectedIndexes();
//    QModelIndex index;
	if(modelIndexList.size() == 0)
		return QVariant();

	QList<RemoteApplication*> rApps;
	setRemoteAppList(rApps);

	/*if((index.row() == 0) && (rApps.size() == 0))
		return QString("Non conosco lo stato o non ci sono applicazioni");*/
	if(index.row() >= rApps.size() )
		return QVariant();

	if (role == Qt::DisplayRole)
	{
		
		if(index.column() == 0) // ritorno il nome dell'applicazione
		{
			return rApps.takeAt(index.row())->getName();
		}
		if(index.column() == 1) // ritorno lo stato
		{
			int status = rApps.takeAt(index.row())->getStatus();
			return statusStrings[status];
		}
			
	}

	return QVariant();
};


QVariant ApplicationTableModel::headerData(int section, Qt::Orientation orientation,
                     int role) const
{
	if (role != Qt::DisplayRole)
         return QVariant();

	QModelIndexList modelIndexList = this->selectionModel->selectedIndexes();
    QModelIndex index;
	if(modelIndexList.size() == 0)
		 return QVariant();
	
	QList<RemoteApplication*> rApps;
	setRemoteAppList(rApps);
	int installed = rApps.size();
	
	/*if(installed == 0)
	{
		if (orientation == Qt::Horizontal)
			if(section == 0)
				return QString("Warning");
		return QVariant();
	}
	else*/
	if (orientation == Qt::Horizontal)
	{
		if(section == 0)
			return QString("Applicazione");
		if(section == 1)
			return QString("Stato");
	}
	     
    //return QString("Row %1").arg(section);
	return QVariant();
};


QModelIndex ApplicationTableModel::MycreateIndex(int row, int column, void *data)
{
	return createIndex(row, column);
};

void ApplicationTableModel::emitReset()
{
	//emit reset();
	reset();
	emit layoutChanged();
}

void ApplicationTableModel::emitDataChanged()
{
	//reset();
	/*QModelIndexList modelIndexList = this->selectionModel->selectedIndexes();
	if(modelIndexList.size() == 0)
		return;
	QVariant variant = modelIndexList.at(0).model()->data(modelIndexList.at(0),Qt::DisplayRole );
	int x = variant.toInt();
	if (client_list->contains(x))
	{	
		ClientLogic* cl = client_list->value(x);
		QList<RemoteApplication*> rApps = cl->getRemoteApplications();
		int size = rApps.size();
		emit dataChanged(index(0,0), index(size, 1));
		
	}*/
	
}